/**
 * Created with CLion.
 * Description: 
 * User: loong
 * Date: 2024/8/13
 * Time: 18:18
 */
#include <gtest/gtest.h>
#include <Doc.h>
#include <fstream>
#include <memory>
using namespace CES::Config;
using namespace std;

// 测试 Node 构造函数
TEST(ConfigTest, ConfigConstructor) {
    auto node = std::make_shared<Node>("key", "value");
    EXPECT_EQ(node->TagName(), "key");
    EXPECT_EQ(node->Value(), "value");
}

//无值单节点创建  ToString
TEST(ConfigTest, ConfigNodeNoValueCreate) {
    auto node = std::make_shared<Node>("foo");

    ASSERT_EQ(node->ToString(), "<foo />\n");
}

//有值单节点创建 ToString
TEST(ConfigTest, ConfigNodeWithValueCreate) {
    auto node = std::make_shared<Node>("foo", "true");

    ASSERT_EQ(node->ToString(), "<foo>true</foo>\n");
    ASSERT_EQ(node->Value(), "true");
}

TEST(ConfigTest, ConfigFromString) {
    auto node = Node::FromString(
        R"(<Menu>
	<foo>true</foo>
	<Foo />
</Menu>
)");

    auto children = node->Children();
    ASSERT_EQ(children.size(), 2);
    EXPECT_EQ(children.front()->TagName(), "foo");
    EXPECT_EQ(children.front()->Value(), "true");
    EXPECT_EQ(children.back()->TagName(), "Foo");
}

TEST(ConfigTest, ConfigFromFile) {
    auto node = Doc::FromFile("./test_output.xml");

    auto children = node->Children();
    ASSERT_EQ(children.size(), 2);
    EXPECT_EQ(children.front()->TagName(), "foo");
    EXPECT_EQ(children.front()->Value(), "true");
    EXPECT_EQ(children.back()->TagName(), "Foo");
}

//自定义缩进
TEST(ConfigTest, ConfigNodeIndent) {
    auto node = std::make_shared<Node>("Menu")->AddChildren({
        std::make_shared<Node>("foo", "true"),
        std::make_shared<Node>("foo", "false")
    });

    ASSERT_EQ(node->ToString(" "),
              R"(<Menu>
 <foo>true</foo>
 <foo>false</foo>
</Menu>
)");

    ASSERT_EQ(node->ToString("#"),
              R"(<Menu>
#<foo>true</foo>
#<foo>false</foo>
</Menu>
)");

    ASSERT_EQ(node->ToString("("),
              R"(<Menu>
(<foo>true</foo>
(<foo>false</foo>
</Menu>
)");
}

// 测试 ToFile 方法
TEST(ConfigTest, ConfigToFile) {
    auto doc = std::make_shared<Doc>("Menu");
    doc->AddChildren({
        std::make_shared<Node>("foo", "true"),
        std::make_shared<Node>("Foo")
    });
    std::string file_path = "./test_output.xml";
    EXPECT_TRUE(doc->ToFile(file_path));

    // 读取文件内容进行比较（假设文件操作代码在其他地方已实现）
    std::ifstream file(file_path);
    std::stringstream buffer;
    buffer << file.rdbuf();

    EXPECT_EQ(buffer.str(),
              R"(<?xml version="1.0"?>
<Menu>
	<foo>true</foo>
	<Foo />
</Menu>
)");
}

// 测试 AddChildren 和 Children 方法
TEST(ConfigTest, ConfigAddAndGetChildren) {
    auto parent = std::make_shared<Node>("parent");
    auto child1 = std::make_shared<Node>("child1");
    auto child2 = std::make_shared<Node>("child2");

    parent->AddChildren({child1, child2});
    NodeList children = parent->Children();

    ASSERT_EQ(children.size(), 2);
    EXPECT_EQ(children.front()->TagName(), "child1");
    EXPECT_EQ(children.back()->TagName(), "child2");
}

// 测试 RemoveChild 方法
TEST(ConfigTest, ConfigRemoveChild) {
    auto parent = std::make_shared<Node>("parent");
    auto child1 = std::make_shared<Node>("child1");
    auto child2 = std::make_shared<Node>("child2");

    auto children = parent->Child("child3");
    ASSERT_EQ(children.size(), 0);

    parent->AddChildren({child1, child2});
    parent->RemoveChild("child1");

    children = parent->Children();
    ASSERT_EQ(children.size(), 1);
    EXPECT_EQ(children.front()->TagName(), "child2");
}

// 测试属性的添加和获取
TEST(ConfigTest, ConfigNormalAddAndGetAttrs) {
    auto node = std::make_shared<Node>("key");
    node->AddAttr("attr1", "value1");
    node->AddAttr("attr2", "value2");

    EXPECT_EQ(node->ToString(),
              R"(<key attr1="value1" attr2="value2" />
)");
    EXPECT_EQ(node->Attr("attr1"), "value1");
    EXPECT_EQ(node->Attr("attr2"), "value2");
    EXPECT_EQ(node->Attr("attr3"), "");
}

TEST(ConfigTest, ConfigAbnormalAddAndGetAttrs) {
    auto node = std::make_shared<Node>("key");
    node->AddAttr("attr1", "value0");
    node->AddAttr("attr1", "value1");

    EXPECT_EQ(node->Attrs().size(), 1);
    EXPECT_EQ(node->Attr("attr1"), "value1");

    node->AddAttr("attr2", "\n\t");
    EXPECT_EQ(node->Attr("attr2"), "\n\t");
}


TEST(ConfigTest, ConfigAttrRemove) {
    auto node = std::make_shared<Node>("key");
    node->AddAttr("attr1", "value1");
    node->AddAttr("attr2", "value2");

    EXPECT_EQ(node->Attrs().size(), 2);

    node->RemoveAttr("attr1");

    EXPECT_EQ(node->Attrs().size(), 1);
    EXPECT_EQ(node->Attr("attr2"), "value2");
}

// 测试 SetTagName 和 TagName 方法
TEST(ConfigTest, ConfigSetAndGetTagName) {
    auto node = std::make_shared<Node>("original");
    node->SetTagName("newTag");
    EXPECT_EQ(node->TagName(), "newTag");
}

// 测试 SetValue 和 Value 方法
TEST(ConfigTest, ConfigSetAndGetValue) {
    auto node = std::make_shared<Node>("key", "initialValue");
    node->SetValue("newValue");
    EXPECT_EQ(node->Value(), "newValue");
}

TEST(ConfigTest, ConfigXPathQuery) {
    auto doc = std::make_shared<Doc>("Menu");
    doc->AddChildren({
        make_shared<Node>("foo", "true"),
        make_shared<Node>("bar", "true"),
        make_shared<Node>("value", "102.3E+06"),
        make_shared<Node>("popups")->AddChildren({
            make_shared<Node>("popup")->AddChildren({
                make_shared<Node>("value", "new"),
                make_shared<Node>("onclick", "CreateNewDoc()")
            }),
            make_shared<Node>("popup")->AddChildren({
                make_shared<Node>("value", "open"),
                make_shared<Node>("onclick", "OpenDoc()")
            })
        })
    });

    auto query = doc->Query(R"(/Menu/popups/popup[2]/onclick)");
    EXPECT_EQ(query.size(), 1);
    EXPECT_EQ(query.front()->Value(), "OpenDoc()");
    EXPECT_EQ(query.front()->TagName(), "onclick");

    query = doc->Query(R"(/Menu/popups/popup[3]/onclick)");
    EXPECT_EQ(query.size(), 0);
}
